package com.atguigu.spzx.log.aspect;

import com.alibaba.fastjson.JSON;
import com.atguigu.spzx.common.handler.exception.SpzxException;
import com.atguigu.spzx.log.annation.SpzxLog;
import com.atguigu.spzx.log.service.SysOperLogService;
import com.atguigu.commom.utils.ThreadLocalUtil;
import com.atguigu.spzx.model.common.ResultCodeEnum;
import com.atguigu.spzx.model.entity.sys.SysOperLog;
import jakarta.servlet.http.HttpServletRequest;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.lang.reflect.Method;

/**
 * title:
 * author: zgl
 * date: 2024/1/8
 * description：
 */
@Aspect
@Component
public class SpzxLogAspect {
    @Autowired
    private SysOperLogService sysOperLogService;

    @Around(value = "@annotation(spzxLog)")
    public Object logAdvance(ProceedingJoinPoint joinPoint, SpzxLog spzxLog) {
        SysOperLog sysOperLog = new SysOperLog();

        try {

            //模块标题
            sysOperLog.setTitle(spzxLog.title());
            //业务类型
            sysOperLog.setBusinessType(spzxLog.businessType());
            //方法名称
            MethodSignature signature = (MethodSignature) joinPoint.getSignature();
            Method method = signature.getMethod();
            String name = method.getDeclaringClass().getName();

            sysOperLog.setMethod(name + method.getName());
            //请求方式
            ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            HttpServletRequest request = requestAttributes.getRequest();
            sysOperLog.setRequestMethod(request.getMethod());
            //操作类别
            sysOperLog.setOperatorType(spzxLog.operatorType().name());
            //操作人员
            sysOperLog.setOperName(ThreadLocalUtil.get().getName());

            //请求Url
            sysOperLog.setOperUrl(request.getRequestURI());
            //主机地址
            sysOperLog.setOperIp(request.getRemoteHost());
            //获取目标方法参数
            Object[] args = joinPoint.getArgs();
            //请求参数
            if (spzxLog.isRequestParam()) {
                sysOperLog.setOperParam(JSON.toJSONString(args));
            }

            //执行目标方法
            Object proceed = joinPoint.proceed(args);

            if (spzxLog.isRequestResponse()) {
                sysOperLog.setJsonResult(JSON.toJSONString(proceed));
            }
            sysOperLog.setStatus(0);
            sysOperLog.setErrorMsg(null);
            //返回执行结果
            return proceed;
        } catch (Throwable e) {
            sysOperLog.setJsonResult(null);
            sysOperLog.setErrorMsg(e.getMessage());
            sysOperLog.setStatus(1);
            throw new SpzxException(ResultCodeEnum.FAIL, e);
        } finally {
            sysOperLogService.save(sysOperLog);
        }
    }
}
